package com.newly.common.base.entity;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.newly.common.base.exception.NewlyException;
import lombok.Data;

import java.io.Serializable;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 分页工具类
 *
 * @author guan
 */
@Data
public class PageUtils<T> implements Serializable {
    private static final long serialVersionUID = 1L;
    /**
     * 总记录数
     */
    private int totalCount;
    /**
     * 每页记录数
     */
    private int pageSize;
    /**
     * 总页数
     */
    private int totalPage;
    /**
     * 当前页数
     */
    private int currPage;
    /**
     * 列表数据
     */
    private List<?> list;

    /**
     * 从source中筛选分页数据
     *
     * @param sources    源集合
     * @param clazz      Class<T>
     * @param offset     页码
     * @param limit      页数
     * @param conditions 条件
     * @return 分页后数据
     */
    public PageUtils(List<T> sources, Class<T> clazz, int offset, int limit, List<Condition> conditions) {
        if (ObjectUtil.isEmpty(sources) || ObjectUtil.isEmpty(clazz)) {
            throw new NewlyException("数据分页失败,source或clazz异常");
        }

        // 条件筛选
        if (!ObjectUtil.isEmpty(conditions)) {
            //conditions.stream().filter()
        }

        // 不匹配的数据
        List<T> removeList = new ArrayList<>();
        if (!ObjectUtil.isEmpty(conditions)) {
            for (T t : sources) {
                for (Condition condition : conditions) {
                    try {
                        Field field = clazz.getDeclaredField(condition.key);
                        field.setAccessible(true);
                        Object fieldObj = field.get(t);
                        if (fieldObj instanceof Date) {

                        } else if (fieldObj instanceof Boolean) {
                            if ((boolean) fieldObj) {
                                removeList.add(t);
                            }
                        } else {
                            if (!field.get(t).toString().contains(condition.value.toString())) {
                                removeList.add(t);
                            }
                        }

                    } catch (Exception e) {
                        throw new NewlyException("[" + condition.key + "]字段不合法!");
                    }
                }
            }
        }

        // 移除关键字不匹配的数据
        sources.removeAll(removeList);

        // 计算分页数据
        int totalCount = sources.size();
        int pageSize = sources.size() > limit ? limit : sources.size();
        int currPage = (offset - 1) * limit;
        int pageNum = sources.size() - 1 >= sources.size() + currPage ? pageSize : pageSize + currPage;
        if (pageSize + currPage > sources.size() - 1) {
            pageNum = sources.size();
        }
        // 需要分页
        List<T> pageList = new ArrayList<>();
        for (int i = currPage; i < pageNum; i++) {
            pageList.add(sources.get(i));
        }
        this.setData(pageList, totalCount, limit, offset);
    }

    /**
     * 分页
     *
     * @param list       列表数据
     * @param totalCount 总记录数
     * @param pageSize   每页记录数
     * @param currPage   当前页数
     */
    public PageUtils(List<?> list, int totalCount, int pageSize, int currPage) {
        this.setData(list, totalCount, pageSize, currPage);
    }

    public PageUtils(IPage<?> page) {
        if (ObjectUtil.isEmpty(page)) {
            return;
        }
        this.setData(page.getRecords(), (int) page.getTotal(), (int) page.getSize(), (int) page.getCurrent());
    }

    private void setData(List<?> list, int totalCount, int pageSize, int currPage) {
        this.list = list;
        this.totalCount = totalCount;
        this.pageSize = pageSize;
        this.currPage = currPage;
        this.totalPage = (int) Math.ceil((double) totalCount / pageSize);
    }

  /*  public PageUtils(PageInfo pageInfo) {
        this(pageInfo.getList(), (int) pageInfo.getTotal(), pageInfo.getPageSize(), pageInfo.getPageNum());
    }*/

    public PageUtils() {
    }

    /**
     * 分页条件
     */
    public static class Condition {
        /**
         * 字段
         */
        private String key;
        /**
         * 值
         */
        private Object value;
        /**
         *
         */
        private ConditionLink conditionLink;

        public Condition(String key, Object value) {
            this.key = key;
            this.value = value;
        }
    }

    /**
     * 分页条件连接关系
     */
    public enum ConditionLink {
        AND, OR;
    }
}